﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using yzrilyzr.FAQ.client;
using yzrilyzr.FAQ.constants;
using yzrilyzr.FAQ.protocol;
using yzrilyzr.FAQ.utils;
using yzrilyzr.util;

namespace FAQ_UI
{
	/// <summary>
	/// ChatMsgList.xaml 的交互逻辑
	/// </summary>
	public partial class ChatMsgList : Page, MsgPackReceiver, IHasToID
	{
		private bool first = true;
		private Logger logger = new Logger("Chat");
		private List<MsgPack> msg = new List<MsgPack>();
		private IChatRecordHelper helper;
		private IChatRecordHelper.Query query;
		private FAQID toid;

		public ChatMsgList()
		{
			InitializeComponent();
			this.DataContext = this;
			FAQUtil.client.addReceiver(this);
			FAQUtil.eventBus.addReceiver(this);
		}

		private void ListOnScroll(object listview, OnScrollEvent e)
		{
			if (ScrollToBottomButton == null) return;
			ScrollToBottomButton.Visibility = Math.Abs(e.y) < 1 ? Visibility.Collapsed : Visibility.Visible;
		}

		private void Page_Unloaded(object sender, RoutedEventArgs e)
		{
			//FAQUtil.eventBus.removeReceiver(this);
			//FAQUtil.client.removeReceiver(this);
		}

		private void Page_Loaded(object sender, RoutedEventArgs e)
		{
			FAQUtil.eventBus.addReceiver(this);
			FAQUtil.client.addReceiver(this);
		}

		public List<MsgPack> BMsgListDataSource
		{ get { return msg; } }

		public MsgEntryHolder BMsgListHolder
		{ get { return new MsgEntryHolder(this,msg, myListView); } }

		public void onItemClick(object listview, OnItemClickEvent e)
		{
			Console.WriteLine(msg[e.index].toString());
		}

		public void update()
		{
			Dispatcher.Invoke(new Action(() => { myListView.notifyDataChanged(); }));
		}

		public void receive(MsgPackTransfer mpt, MsgPack p)
		{
			int i = p.getCmd();
			if (p.isMsg() && p.getFrom().equals(toid) || p.getCmd() == C.FRONTEND_FROM_ME_UPDATE)
			{
				MsgPack p1 = p;
				if (p1.getCmd() == C.FRONTEND_FROM_ME_UPDATE)
				{
					p1 = new BinMsgPack(p1.getData());
					if (!p1.getFrom().equals(toid) && !p1.getFrom().equals(FAQUtil.client.getFAQID())) return;
				}
				if (p1.getCmd() == C.RECALL)
				{
					FAQID pkgid = p1.getPkgid();
					foreach (MsgPack x in msg)
					{
						if (x.getPkgid().equals(pkgid))
						{
							x.setCmd(C.RECALL);
							break;
						}
					}
				}
				else
				{
					foreach(MsgPack a in msg)
					{
						if (a.getPkgid().equals(p1.getPkgid())) return;
					}
					msg.Insert(0, p1);
				}
				update();
			}
			else if (p.getCmd() == C.ACK)
			{
				foreach (MsgPack x in msg)
				{
					if (x.getPkgid().equals(p.getPkgid()))
					{
						if (p.getFrom().equals(UUIDs.SERVER))
						{
							x.updateMsgState(MsgState.SERVER_CACHE);
						}
						else if (p.getFrom().equals(x.getTo()))
						{
							x.updateMsgState(MsgState.RECEIVED);
							if (!p.getBoolean(K.READSUCCESS)) x.updateMsgState(MsgState.READ_FAIL);
						}
						update();
						break;
					}
				}
			}
			else if (p.getCmd() == C.NEEDDIGEST)
			{
				update();
			}
			else if (p.getCmd() == C.ISREAD)
			{
				foreach (MsgPack x in msg)
				{
					if (x.getPkgid().equals(p.getPkgid()))
					{
						x.addIsRead(p.getFromUser());
						update();
						break;
					}
				}
			}
			else if (i == App.OPEN_CHAT)
			{
				toid = p.getTo();
				logger.i("ChatMsgListTo", toid);
				query = null;
				helper = FAQUtil.client.getChatRecordHelper(toid);
				msg.Clear();
				first = true;
				loadMsg();
			}
			else if (i == App.CLOSE_CHAT)
			{
				query = null;
				msg.Clear();
				first = true;
			}
		}

		private void loadMsg()
		{
			if (query == null) query = helper.query();
			MsgPack[] pa = query.next(50);
			if (pa != null)
			{
				List<MsgPack> pa2 = new List<MsgPack>(pa);
				pa2.Sort((p1, p2) =>
				{
					if (p1.getTime() == p2.getTime()) return 0;
					return p1.getTime() > p2.getTime() ? -1 : 1;
				});
				MsgPack msp = null;
				if (msg.Count != 0) msp = msg[0];
				msg.AddRange(pa2);
				mergeMsg();
				Dispatcher.Invoke(new Action(() =>
				{
					if (first)
					{
						myListView.notifyDataInvalidated();
						first = false;
					}
					else myListView.notifyDataChanged();
				}));
			}
		}

		private void mergeMsg()
		{
			for (int i = 0; i < msg.Count - 1; i++)
			{
				MsgPack r = msg[i];
				MsgPack t = msg[i + 1];
				if (r.getCmd() == C.MSG_TIME && t.getCmd() == C.MSG_TIME)
				{
					msg.Remove(r);
					i--;
					continue;
				}
				if (t.getTime() - r.getTime() > 5 * 60 * 1000 && t.getCmd() != C.SMSG)
				{
					MsgPack pp = new BinMsgPack(C.MSG_TIME).setTime(t.getTime())
														  .setData(string.Format("{0:yyyy-MM-dd HH:mm:ss}", new DateTime(t.getTime())));
					msg.Insert(i + 1, pp);
				}
			}
		}

		private void ScrollToBottom(object sender, System.Windows.Input.MouseButtonEventArgs e)
		{
			myListView.setSelection(0);
		}

		public FAQID getTo()
		{
			return toid;
		}
	}
}